package com.ruoyi.common.utils;

import com.ruoyi.common.annotation.Excel;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.ss.util.CellRangeAddress;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;

import static com.ruoyi.common.utils.DateUtils.YYYY_MM_DD_HH_MM_SS;

public class CustomExcelExporter<T> {

    private final Class<T> clazz;

    public CustomExcelExporter(Class<T> clazz) {
        this.clazz = clazz;
    }

    /**
     * 导出 Excel 并在顶部添加标题和副标题
     *
     * @param response   HTTP 响应
     * @param data       数据列表
     * @param fileName   文件名
     * @param title      主标题
     * @param subtitle   副标题
     */
    public void exportExcelWithHeader(HttpServletResponse response, List<T> data, String fileName, String title, String subtitle) {
        try (Workbook workbook = new XSSFWorkbook()) {
            Sheet sheet = workbook.createSheet("Sheet1");

            // 创建标题和副标题行
            createTitleAndSubtitle(sheet, title, subtitle);

            // 写入数据到 Excel 表格
            writeDataToSheet(sheet, data);

            // 自动调整列宽
            autoSizeColumns(sheet);

            // 输出 Excel 到 HTTP 响应
            writeWorkbookToResponse(workbook, response, fileName);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void createTitleAndSubtitle(Sheet sheet, String title, String subtitle) {
        // 创建标题行
        Row titleRow = sheet.createRow(0);
        Cell titleCell = titleRow.createCell(0);
        titleCell.setCellValue(title);
        titleCell.setCellStyle(getTitleCellStyle(sheet.getWorkbook()));
        sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 9)); // 合并单元格

        // 创建副标题行
        Row subtitleRow = sheet.createRow(1);
        Cell subtitleCell = subtitleRow.createCell(0);
        subtitleCell.setCellValue(subtitle);
        subtitleCell.setCellStyle(getSubtitleCellStyle(sheet.getWorkbook()));
        sheet.addMergedRegion(new CellRangeAddress(1, 1, 0, 9)); // 合并单元格
    }

    private CellStyle getTitleCellStyle(Workbook workbook) {
        CellStyle style = workbook.createCellStyle();
        Font font = workbook.createFont();
        font.setBold(true); // 标题加粗
        font.setFontHeightInPoints((short) 16); // 标题字体大小
        style.setFont(font);
        style.setAlignment(HorizontalAlignment.CENTER); // 水平居中
        style.setVerticalAlignment(VerticalAlignment.CENTER); // 垂直居中
        return style;
    }

    private CellStyle getSubtitleCellStyle(Workbook workbook) {
        CellStyle style = workbook.createCellStyle();
        Font font = workbook.createFont();
        font.setFontHeightInPoints((short) 12); // 副标题字体较小
        style.setFont(font);
        style.setAlignment(HorizontalAlignment.RIGHT); // 副标题右对齐
        style.setVerticalAlignment(VerticalAlignment.CENTER); // 垂直居中
        return style;
    }


    private void writeDataToSheet(Sheet sheet, List<T> data) {
        if (data.isEmpty()) {
            return;
        }

        // 获取带有 @Excel 注解的字段，并读取注解中的名称
        List<Field> excelFields = new ArrayList<>();
        List<String> headers = new ArrayList<>();

        for (Field field : clazz.getDeclaredFields()) {
            Excel excel = field.getAnnotation(Excel.class);
            if (excel != null) {
                field.setAccessible(true);
                excelFields.add(field);
                headers.add(excel.name());
            }
        }

        // 创建表头行
        Row headerRow = sheet.createRow(2);
        for (int i = 0; i < headers.size(); i++) {
            Cell cell = headerRow.createCell(i);
            cell.setCellValue(headers.get(i));
            cell.setCellStyle(getHeaderCellStyle(sheet.getWorkbook()));
        }

        // 写入数据到表格中
        int rowIndex = 3; // 数据从第4行开始，前3行为标题、副标题和表头
        SimpleDateFormat dateFormat = new SimpleDateFormat(YYYY_MM_DD_HH_MM_SS); // 日期格式
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(YYYY_MM_DD_HH_MM_SS); // LocalDateTime格式

        for (T item : data) {
            Row dataRow = sheet.createRow(rowIndex++);
            for (int i = 0; i < excelFields.size(); i++) {
                Field field = excelFields.get(i);
                try {
                    Object value = field.get(item);
                    Cell cell = dataRow.createCell(i);

                    // 判断字段类型是否为 Date 或 LocalDateTime，并进行格式化
                    if (value instanceof Date) {
                        String formattedDate = dateFormat.format((Date) value);
                        cell.setCellValue(formattedDate);
                    } else if (value instanceof LocalDateTime) {
                        String formattedDateTime = ((LocalDateTime) value).format(dateTimeFormatter);
                        cell.setCellValue(formattedDateTime);
                    } else {
                        cell.setCellValue(value == null ? "" : value.toString());
                    }

                    cell.setCellStyle(getDataCellStyle(sheet.getWorkbook()));
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private CellStyle getHeaderCellStyle(Workbook workbook) {
        CellStyle style = workbook.createCellStyle();
        Font font = workbook.createFont();
        font.setBold(false); // 不加粗
        font.setFontHeightInPoints((short) 12);
        style.setFont(font);
        style.setAlignment(HorizontalAlignment.CENTER); // 表头水平居中
        style.setVerticalAlignment(VerticalAlignment.CENTER); // 表头垂直居中
        return style;
    }

    private CellStyle getDataCellStyle(Workbook workbook) {
        CellStyle style = workbook.createCellStyle();
        Font font = workbook.createFont();
        font.setFontHeightInPoints((short) 12);
        style.setFont(font);
        style.setAlignment(HorizontalAlignment.CENTER); // 数据单元格水平居中
        style.setVerticalAlignment(VerticalAlignment.CENTER); // 数据单元格垂直居中
        style.setWrapText(true); // 自动换行
        return style;
    }

    private void autoSizeColumns(Sheet sheet) {
        int columnCount = sheet.getRow(2).getPhysicalNumberOfCells(); // 表头列数
        for (int i = 0; i < columnCount; i++) {
            sheet.autoSizeColumn(i); // 自动调整列宽
            // 适当增加宽度以适应中文字符
            sheet.setColumnWidth(i, sheet.getColumnWidth(i) * 16 / 10);
        }
    }

    private void writeWorkbookToResponse(Workbook workbook, HttpServletResponse response, String fileName) throws IOException {
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8") + ".xlsx");

        try (ServletOutputStream outputStream = response.getOutputStream()) {
            workbook.write(outputStream);
        }
    }
}
